package com.mew.lobby.net;


import com.mew.common.dc.db.MaintenanceService;
import com.mew.common.dc.redis.AucRedisService;
import com.mew.common.enm.ExitType;
import com.mew.common.rest.bo.MewSession;
import com.mew.lobby.config.LobbySession;
import com.mew.lobby.config.LobbySessionManager;
import com.mew.lobby.provide.LoginExitFeignService;
import com.zebra.common.OfflineType;
import com.zebra.common.OnlineType;
import com.zebra.remoting.config.BasisCommandCode;
import com.zebra.remoting.config.EmptyMessage;
import com.zebra.remoting.config.StateCode;
import com.zebra.remoting.config.TmsServerInfo;
import com.zebra.remoting.connection.Connection;
import com.zebra.remoting.protocol.ZebraCommand;
import com.zebra.remoting.tms.AbstractServerHandler;
import com.zebra.remoting.tms.TmsConfigInfoManager;
import com.zebra.remoting.tms.TmsSendMessageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@Slf4j
public class ConnectionHandlerService extends AbstractServerHandler {

    @Autowired
    private AucRedisService aucRedisService;
    @Autowired
    private LoginExitFeignService loginExitFeignService;

    @Override
    public void doHandler(ZebraCommand zebraCommand) throws Exception {

        MewSession session = aucRedisService.getSession(zebraCommand.getUserId());
        LobbySession lobbySession = LobbySessionManager.getInstance().getSession(zebraCommand.getUserId());
        if (BasisCommandCode.SWITCHTMS.cmd() == zebraCommand.getCmd()){
            if (session == null){
                log.error("Handler SWITCHTMS MewSession is null {}", zebraCommand.toString());
                return;
            }
            log.info("Handler SWITCHTMS {}", zebraCommand);

            int serverId = TmsConfigInfoManager.getInstance().getServerInfo().getServerId();
            if (serverId != session.lsid){
                MewSession other = new MewSession();
                other.lsid = serverId;
                aucRedisService.updateSession(zebraCommand.getUserId(), other);
            }
            lobbySession = null == lobbySession ? new LobbySession() : lobbySession;
            lobbySession.setChannel(zebraCommand.getChannel());
            lobbySession.setTk(zebraCommand.getToken());
            lobbySession.setUserId(zebraCommand.getUserId());
            LobbySessionManager.getInstance().putSession(lobbySession);
            return;
        }

        if (BasisCommandCode.OFFLINE.cmd() == zebraCommand.getCmd()){
            log.error("Handler offline: OFFLINE ltk:{}  {} {}", null == lobbySession ? "lobSession is null" : lobbySession.getTk(),  zebraCommand, null == session ? " session is null" : session.toString());
            offlineByGW(zebraCommand, session, lobbySession);
            return;
        }

        //-----校验-------------
        if (zebraCommand.getCommandModel().isVerifyType()) {
            if (null == session || session.tk != zebraCommand.getToken()){
                zebraCommand.sendFailureCode(StateCode.LoginUn.code());
                log.error("Handler offline: session failure   {} ses:{}", zebraCommand, null == session ? "" : session.toString());
                offline(lobbySession);
                return;
            }
        }

        if (null != lobbySession && lobbySession.getWhiteList() == 0 && aucRedisService.getMaintenance()){
            log.info("*****Sys maintenance ****** ");
            aucRedisService.offlineSession(lobbySession.getUserId());
            TmsSendMessageUtil.pushMessage(zebraCommand.getChannel(), BasisCommandCode.OVERHAULED.cmd(), lobbySession.getUserId(), lobbySession.getTk(), new EmptyMessage());
            LobbySessionManager.getInstance().removeSession(lobbySession.getUserId());
            return;
        }

        TmsServerInfo tmsServerInfo = TmsConfigInfoManager.getInstance().getServerInfo();
        if (tmsServerInfo.getOnline() < OnlineType.Online.value()){
            log.info("*****Lobby TMS offline {}", tmsServerInfo);
            aucRedisService.offlineSession(lobbySession.getUserId());
            TmsSendMessageUtil.pushMessage(zebraCommand.getChannel(), BasisCommandCode.OVERHAULED.cmd(), lobbySession.getUserId(), lobbySession.getTk(), new EmptyMessage());
            LobbySessionManager.getInstance().removeSession(lobbySession.getUserId());
            return;
        }

        MewHandler mewHandler = InitializeHandlerMapping.getMapping(zebraCommand.getCmd());
        if (null == mewHandler){
            log.error("Handler MewHandler <-> CMD is null {}", zebraCommand);
            zebraCommand.sendFailureCode(StateCode.LoginUn.code());
            offline(lobbySession);
            return;
        }

        mewHandler.handle(zebraCommand, session);
    }


    @Override
    public void doChannelInactive(Connection connection) throws Exception {
        List<LobbySession> list = LobbySessionManager.getInstance().findByChannel(connection.getChannel());
        if (null == list || list.isEmpty()){
            return;
        }
        log.error("Handler Gateway inactive: {}", connection);
        list.forEach(ls ->  {
            log.error("Handler Gateway inactive session: {}", ls.toString());
            offline(ls);
        });

    }

    @Override
    public void doTmsOffline() {
        log.info("------------RA-to-TMS-Offline--1 M-exe---user-offline---------------");
    }

    private void offline(LobbySession lobbySession){
        if (null == lobbySession){
            return;
        }
        aucRedisService.offlineSession(lobbySession.getUserId(), lobbySession.getTk());
        LobbySessionManager.getInstance().removeSession(lobbySession.getUserId());
    }



    private void offlineByGW(ZebraCommand<EmptyMessage> command,  MewSession session, LobbySession lobbySession){
        long userId = command.getUserId();
        if (null == lobbySession){
            return;
        }

        if (null == session || lobbySession.getTk() != session.tk){
            LobbySessionManager.getInstance().removeSession(userId);
            return;
        }

        if (command.getToken() != session.tk){
            return;
        }

        if (OfflineType.InactiveDiff.code() == command.getRequest().getMsg()
                || (OfflineType.Push.code() == command.getRequest().getMsg() && OnlineType.Online.value() == session.onl)){
            return;
        }

        if (OfflineType.Expired.code() == command.getRequest().getMsg()){
            loginExitFeignService.exitLobby(userId, ExitType.Expires.code());
        }else if (OfflineType.Repeat.code() != command.getRequest().getMsg()) {
            aucRedisService.offlineSession(lobbySession.getUserId(), lobbySession.getTk());
        }
        LobbySessionManager.getInstance().removeSession(userId);

    }

}



